package com.pbd.client.tag;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.pbd.client.MemberSearchGrid;
import com.pbd.client.utils.LoadingBox;

public class TagCloud extends Composite {

	private FlowPanel cloud;
	private List<Tag> tags;
	private int maxNumberOfTags;
	private double minOccurences, maxOccurences, step;
	private boolean isColored;

	private static final int STEP_NUMBER = 10;

	public TagCloud() {
		cloud = new FlowPanel();
		cloud.setStyleName("cloud");
		tags = new ArrayList<Tag>();
		maxNumberOfTags = 20;
		minOccurences = 1;
		maxOccurences = 1;
		step = 1;// 'average' difference between each occurence
		DecoratorPanel dec = new DecoratorPanel();
		dec.setWidth("296");
		dec.setHeight("393");
		// dec.setWidget(cloud);
		initWidget(cloud);
	}

	public void populate(List<WordTag> tagList) {

		for (WordTag wordTag : tagList) {
			addWord(new WordTag(wordTag.getWord(), wordTag.getWord()));
		}

		for (int i = 0; i < tagList.size(); i++) {
			double r = Math.random() * 50;
			int seed = (int) Math.floor(r) + 1;
			for (int j = 0; j < tagList.size(); j++) {
				if (j == seed) {
					tags.get(j).increaseNumberOfOccurences();
				}
			}
		}

		refresh();
	}

	/**
	 * Set the whole list of tags given in paramter to be the current tags list.
	 * 
	 * @param tags
	 */
	public void setTags(List<Tag> tags) {
		if (this.tags == null)
			this.tags = new ArrayList<Tag>();
		this.tags.clear();
		if (tags != null)
			this.tags.addAll(tags);
	}

	/**
	 * Add a word to the tagcloud list.
	 * 
	 * @param word
	 */
	public void addWord(WordTag word) {
		boolean exist = false;
		for (Tag t : tags) {
			if (((WordTag) t).getWord().equalsIgnoreCase(word.getWord())) {
				t.increaseNumberOfOccurences();
				exist = true;
			}
		}
		if (!exist)
			tags.add(word);
		refresh();
	}

	/**
	 * Add an image to the tagcloud list
	 * 
	 * @param image
	 */
	public void addImage(ImageTag image) {
		boolean exist = false;
		for (Tag w : tags) {
			if (w instanceof ImageTag) {
				if (((ImageTag) w).getUrl().equalsIgnoreCase(image.getUrl())) {
					w.increaseNumberOfOccurences();
					exist = true;
				}
			}
		}
		if (!exist)
			tags.add(image);
		refresh();
	}

	/**
	 * Refresh the display of the tagcloud. Usually used after an adding of
	 * word.
	 */
	public void refresh() {
		cloud.clear();
		if (tags != null && !tags.isEmpty()) {
			// recalculate max and min of all occurences
			for (Tag w : tags) {
				if (w.getNumberOfOccurences() > maxOccurences)
					maxOccurences = w.getNumberOfOccurences();
				if (w.getNumberOfOccurences() < minOccurences)
					minOccurences = w.getNumberOfOccurences();
			}

			// a step correspond to a css style.
			step = (maxOccurences - minOccurences) / STEP_NUMBER;

			for (Tag w : tags) {
				InlineHTML inline = null;
				if (w instanceof WordTag)
					inline = setInlineHTML((WordTag) w);
				else {
					Image ima = ((ImageTag) w).getImage();
					inline = new InlineHTML(" <a href='" + w.getLink() + "'><img src='" + ima.getUrl() + "'</a>");
					inline.addStyleName("tag");
				}

				cloud.add(inline);
			}
		}
	}

	public List<Tag> getTags() {
		return tags;
	}

	private void setWordOrientation(String word, int orientation) {
		List<Tag> tags = getTags();
		if (tags != null) {
			for (Tag t : tags) {
				if (((WordTag) t).getWord().equalsIgnoreCase(word))
					((WordTag) t).setOrientation(orientation);
			}
		}
	}

	/**
	 * Create the 'CSS' aspect of the given word thanks the whole minimum,
	 * maximum, and average number of occurences of all words. It create a link
	 * in a span with the appropriate font style/size
	 * 
	 * @param w
	 *            The Word object to display
	 * @return The InlinHTML object that fits in the cloud
	 */
	private InlineHTML setInlineHTML(WordTag w) {
		int nboc = w.getNumberOfOccurences();

		InlineHTML inline = new InlineHTML(" <a href='javascript:;'>" + w.getWord() + "</a>&nbsp;");
		// + w.getLink() + "'>"
		inline.addStyleName("tag");

		if (nboc >= (maxOccurences - step)) {
			inline.addStyleName("tag10");
		} else if (nboc >= (maxOccurences - (step * 2))) {
			inline.addStyleName("tag9");
		} else

		if (nboc >= (maxOccurences - (step * 3))) {
			inline.addStyleName("tag8");
		} else if (nboc >= (maxOccurences - (step * 4))) {
			inline.addStyleName("tag7");
		} else if (nboc >= (maxOccurences - (step * 5))) {
			inline.addStyleName("tag6");
		} else if (nboc >= (maxOccurences - (step * 6))) {
			inline.addStyleName("tag5");
		} else if (nboc >= (maxOccurences - (step * 7))) {
			inline.addStyleName("tag4");
		} else if (nboc >= (maxOccurences - (step * 8))) {
			inline.addStyleName("tag3");
		}
		// else if (nboc >= (maxOccurences - (step * 9))) {
		// inline.addStyleName("tag2");
		// } else if (nboc >= (maxOccurences - (step * 10))) {
		// inline.addStyleName("tag1");
		// }

		// applying color if needed
		if (isColored) {
			double r = Math.random() * 10;
			int seed = (int) Math.floor(r) + 1;
			switch (seed) {
			case 1:
				inline.addStyleName("red");
				break;
			case 2:
				inline.addStyleName("orange");
				break;
			case 3:
				inline.addStyleName("green");
				break;
			case 4:
				inline.addStyleName("lightblue");
				break;
			case 5:
				inline.addStyleName("purple");
				break;
			case 6:
				inline.addStyleName("blue");
				break;
			case 7:
				inline.addStyleName("pink");
				break;
			case 8:
				inline.addStyleName("brown");
				break;
			case 9:
				inline.addStyleName("blue");
				break;
			case 10:
				inline.addStyleName("grey");
				break;
			default:
				inline.addStyleName("black");
				break;
			}
		}

		inline.addClickHandler(new TagClickHandler(w));
		return inline;
	}

	public int getMaxNumberOfWords() {
		return maxNumberOfTags;
	}

	public void setMaxNumberOfWords(int numberOfWords) {
		this.maxNumberOfTags = numberOfWords;
	}

	public boolean isColored() {
		return isColored;
	}

	/**
	 * Set whither you wan the tags to be colored randomly.
	 * 
	 * @param isColored
	 */
	public void setColored(boolean isColored) {
		this.isColored = isColored;
		if (this.isColored)
			refresh();
	}

	public class TagClickHandler implements ClickHandler {
		private WordTag wordtag;

		public TagClickHandler(WordTag w) {
			this.wordtag = w;

		}

		@Override
		public void onClick(ClickEvent event) {

			String businessCategory = wordtag.getLink();
			String whereClause = "BUSINESSCATEGORY.name='"+businessCategory+"' AND PARTY.isActive=true ";
			FlexTable mainTable = (FlexTable)RootPanel.get("mainContainer").getWidget(0);
			mainTable.clear();
			mainTable.setCellSpacing(8);
			LoadingBox.getSharedInstance().show();
			mainTable.setWidget(0, 0, new MemberSearchGrid(whereClause,  new String[] { "businessCategoryRelation.businessCategory.id" }));
		
			FlexTable adsTable = new FlexTable();
			adsTable.setStyleName("gray_box");
			adsTable.setWidth("250px");
			adsTable.setHeight("757px");
			adsTable.setWidget(0, 0, new HTML("<p><span class=\"body_txt_black\"></span><span class=\"heading_blue_s2\"><br></span><span class=\"heading_blue\">ADVERTISE<br>YOUR<br>BUSINESS</span><span class=\"body_txt_black1\"><br><br></span><span class=\"heading_orange\"><font color=\"#00e1ff\" size=\"+4\"><b>HERE</b></font></span><br><br></p><p class=\"heading_orange1\"><span class=\"body_txt_black\">Please Contact:</span><br><img src=\".\\images\\phone_icon.png\"/>&nbsp&nbsp<span class=\"heading_orange1\">6529 1930 / 2235 0986</span></p>"));
			mainTable.setWidget(0, 1, adsTable);

		}
	}
}
